/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.absisgroup.nsc.users;

import com.absisgroup.nsc.utilities.DBUtilities;
import com.absisgroup.nsc.utilities.EntityManager;
import com.absisgroup.nsc.utilities.GenericServlet;
import com.absisgroup.nsc.utilities.Util;
import java.math.BigDecimal;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author Hue
 */
public class LogonAction extends GenericServlet {
    private final int INVALID    = 1;
    private final int INACTIVE   = 2;
    private final int DONTEXIST  = 5;

    @Override
    public int process(final Connection con, final HttpServletRequest request, final HttpServletResponse response) throws Exception {
        final String cookieLanguage = getCookieLanguage(request);
        initUserLocale(request, cookieLanguage);
        if("POST".equals(request.getMethod())) {
            final String strLogin = request.getParameter("userLogon");
            if(strLogin == null || strLogin.isEmpty()) {
                return RUN_JSP;
            }
            final int iValidate = validate(con, request, response, strLogin, cookieLanguage);
            switch(iValidate) {
                case INVALID :
                case DONTEXIST:
                    request.setAttribute("login.invalid","true");            
                    return RUN_JSP;
                case INACTIVE :
                    request.setAttribute("login.inactive","true");
                    return RUN_JSP;
            }
            response.sendRedirect("Home.jsp");
            return DONT_RUN_JSP;
        }
        return RUN_JSP;
    }
    
    public int validate(final Connection con, final HttpServletRequest request, final HttpServletResponse response, final String strLogin, final String cookieLanguage) throws Exception {
        request.getSession().invalidate();
        final String modPK = getModPK();
        final boolean bLoginCaseSensitive = "TRUE".equals(DBUtilities.findDefaultValue(con, "0", "LOGIN", "LOGIN_CASE_SENSITIVE"));
        final String strQuery = "select USR_PK, USR_LOGIN, USR_INITIAL, USR_PASSWORD, USR_CREATION_DATE, USR_LASTCHANGE_PWD, USR_NUMBER_ATTEMPT, USR_FIRST_NAME, USR_LAST_NAME, " + 
                                "       USR_STATE, USR_LANGUAGE, USR_PHONE, USR_FAX, USR_EMAIL, USR_GSM, USR_PHONE_GEN, USR_TITLE, USR_DEPARTMENT, USR_STREET1, USR_STREET2, USR_LOC_FK, " + 
                                "       USR_COMPANY, USR_RIGHT_GROUP, USR_EXTERNAL_LOGIN, USR_EXTERNAL_PASSWORD, USR_XLS_NUMBER_FORMAT, USR_XLS_DATE_FORMAT, USR_ISTIMESHEET, USR_INIT_PASSWORD, " + 
                                "       USR_USER_FK, USR_ORDER_MAX_APPROVAL_AMOUNT, USR_ISARCHIVED, USR_ABY_USR_FK, USR_RECORD_LIMIT, USR_RECORD_LIMIT_XLS, USR_RECORD_LIMIT_PDF " + 
                                "from users, user_modules " + 
                                "where usr_pk = usrmod_usr_fk and usrmod_mod_fk = ? " + 
                                "and " + (bLoginCaseSensitive ? "usr_login = ?" : "upper(usr_login) = upper(?)");
        final List params = new ArrayList();
        params.add(modPK);
        params.add(strLogin);
        final List list = EntityManager.findByQuery(con, UsersEntity.class, strQuery, params);
        UsersEntity entity = null;
        if(list.size() > 0) {
            entity = (UsersEntity) list.get(0);
        }
        if(entity == null) {
            return DONTEXIST;
        }
        else if(entity.getUsrState() == null || entity.getUsrState().intValue() == 0) {
            return INACTIVE;
        }
        final String pwdCaseSensitive  = DBUtilities.findDefaultValue(con, "0", "LOGIN", "PWD_CASE_SENSITIVE");
        final String pwdEncoded  = DBUtilities.findDefaultValue(con, "0", "LOGIN", "PWD_ENCODED");
        String password = request.getParameter("userPassword");
        if("TRUE".equals(pwdEncoded)) {
            password = Util.hashPassword(password);
        }
        //the check PWD_CASE_SENSITIVE = FALSE is only available if PWD_ENCODED = FALSE
        //because the the method equalsIgnoreCase doesn't work with the encoded password
        boolean bValidPassword;
        if("TRUE".equals(pwdCaseSensitive)) {
            bValidPassword = entity.getUsrPassword().equals(password);
        }
        else {
            bValidPassword = entity.getUsrPassword().equalsIgnoreCase(password);
        }
        if(!bValidPassword) {
            final int pwdFailedLogin = Util.toInt(DBUtilities.findDefaultValue(con, "0", "LOGIN", "PWD_FAILED_LOGIN"));
            if(pwdFailedLogin > 0) {
                BigDecimal usrNumberAttempt = (entity.getUsrNumberAttempt() == null ? new BigDecimal(0) : entity.getUsrNumberAttempt());
                usrNumberAttempt = usrNumberAttempt.add(new BigDecimal(1));
                entity.setUsrNumberAttempt(usrNumberAttempt);
                if(usrNumberAttempt.intValue() >= pwdFailedLogin) {
                    // lock user
                    entity.setUsrState(new BigDecimal("0"));
                }
                if(EntityManager.store(con, entity)) {
                    con.commit();
                }
                else {
                    con.rollback();
                }
            }
            return INVALID;
        }
        request.getSession().setAttribute(USER_KEY, entity);
        String language;
        if(cookieLanguage == null) {
            //we must find the language before translating the default organization position
            language = DBUtilities.findDefaultValue(con, modPK, "GENERAL","LANGUAGE");
            if(language == null || "".equals(language.trim())) {
                language = entity.getUsrLanguage();
            }
            initUserLocale(request, language);
        }
        else {
            language = cookieLanguage;
        }
        //session time out [
        final String strSessionTime  = DBUtilities.findDefaultValue(con, "0", "LOGIN", "SESSION_TIME");
        final int time = Util.toInt(strSessionTime);
        if(time == 0) {
            request.getSession().setMaxInactiveInterval(-1);
        }
        else {
            request.getSession().setMaxInactiveInterval(time * 60);
        }
        //]
        //Reinitialize USR_NUMBER_ATTEMPT when the password is ok
        entity.setUsrNumberAttempt(new BigDecimal("0"));
        if(EntityManager.store(con, entity)) {
            con.commit();
        }
        else {
            con.rollback();
        }
        final Cookie cookie = new Cookie("USR_LANGUAGE", language);
        cookie.setMaxAge(30 * 24 * 60 * 60);//30 days
        response.addCookie(cookie);

        return 0; //successful
    }
    
    private void initUserLocale(final HttpServletRequest request, final String language) {
        request.getSession().setAttribute(org.apache.struts.action.Action.LOCALE_KEY, getLocale(language));
    }
    
    private Locale getLocale(final String _strLangApp) {
        Locale defaultLocale = new Locale("fr","FR");//default language is French.
        if(_strLangApp == null || _strLangApp.isEmpty()) {
            return defaultLocale;
        }

        final int iIndex = _strLangApp.indexOf("_");
        if(iIndex != -1) {
            return new Locale(_strLangApp.substring(0,iIndex),_strLangApp.substring(iIndex+1));
        }
        return defaultLocale;
    }
    
    private String getCookieLanguage(final HttpServletRequest request) {
        final Cookie[] cookies = request.getCookies();
        if(cookies == null) {
            return null;
        }
        final int iLength = cookies.length;
        for(int i=0; i<iLength; i++) {
            if("USR_LANGUAGE".equals(cookies[i].getName())) {
                String cookieLanguage = cookies[i].getValue();
                if(cookieLanguage != null && cookieLanguage.startsWith("en_")) {
                    cookieLanguage = "en_EN";
                }
                return cookieLanguage;
            }
        }

        return null;
    }
}
